home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / CSG.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-25  |  21.2 KB  |  1,090 lines

  1. /****************************************************************************
  2. *                   csg.c
  3. *
  4. *  This module implements routines for constructive solid geometry.
  5. *
  6. *  from Persistence of Vision(tm) Ray Tracer
  7. *  Copyright 1996 Persistence of Vision Team
  8. *---------------------------------------------------------------------------
  9. *  NOTICE: This source code file is provided so that users may experiment
  10. *  with enhancements to POV-Ray and to port the software to platforms other
  11. *  than those supported by the POV-Ray Team.  There are strict rules under
  12. *  which you are permitted to use this file.  The rules are in the file
  13. *  named POVLEGAL.DOC which should be distributed with this file. If
  14. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  15. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  16. *  Forum.  The latest version of POV-Ray may be found there as well.
  17. *
  18. * This program is based on the popular DKB raytracer version 2.12.
  19. * DKBTrace was originally written by David K. Buck.
  20. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  21. *
  22. *****************************************************************************/
  23.  
  24. #include "frame.h"
  25. #include "povray.h"
  26. #include "vector.h"
  27. #include "povproto.h"
  28. #include "bbox.h"
  29. #include "csg.h"
  30. #include "hfield.h"
  31. #include "matrices.h"
  32. #include "objects.h"
  33. #include "planes.h"
  34. #include "quadrics.h"
  35.  
  36.  
  37.  
  38. /*****************************************************************************
  39. * Local preprocessor defines
  40. ******************************************************************************/
  41.  
  42.  
  43.  
  44.  
  45. /*****************************************************************************
  46. * Static functions
  47. ******************************************************************************/
  48.  
  49. static int All_CSG_Union_Intersections PARAMS((OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack));
  50. static int All_CSG_Merge_Intersections PARAMS((OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack));
  51. static int All_CSG_Intersect_Intersections PARAMS((OBJECT *Object, RAY *Ray, ISTACK *Depth_Stack));
  52. static int Inside_CSG_Union PARAMS((VECTOR point, OBJECT *Object));
  53. static int Inside_CSG_Intersection PARAMS((VECTOR point, OBJECT *Object));
  54. static void *Copy_CSG PARAMS((OBJECT *Object));
  55. static void Translate_CSG PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  56. static void Rotate_CSG PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  57. static void Scale_CSG PARAMS((OBJECT *Object, VECTOR Vector, TRANSFORM *Trans));
  58. static void Transform_CSG PARAMS((OBJECT *Object, TRANSFORM *Trans));
  59. static void Destroy_CSG PARAMS((OBJECT *Object));
  60. static void Invert_CSG_Union PARAMS((OBJECT *Object));
  61. static void Invert_CSG_Intersection PARAMS((OBJECT *Object));
  62.  
  63.  
  64. /*****************************************************************************
  65. * Local variables
  66. ******************************************************************************/
  67.  
  68. METHODS CSG_Union_Methods =
  69. {
  70.   All_CSG_Union_Intersections,
  71.   Inside_CSG_Union, NULL /*Normal*/,
  72.   Copy_CSG,
  73.   Translate_CSG, Rotate_CSG,
  74.   Scale_CSG, Transform_CSG, Invert_CSG_Union, Destroy_CSG
  75. };
  76.  
  77. METHODS CSG_Merge_Methods =
  78. {
  79.   All_CSG_Merge_Intersections,
  80.   Inside_CSG_Union, NULL /*Normal*/,
  81.   Copy_CSG,
  82.   Translate_CSG, Rotate_CSG,
  83.   Scale_CSG, Transform_CSG, Invert_CSG_Union, Destroy_CSG
  84. };
  85.  
  86. METHODS CSG_Intersection_Methods =
  87. {
  88.   All_CSG_Intersect_Intersections,
  89.   Inside_CSG_Intersection, NULL /*Normal*/,
  90.   Copy_CSG,
  91.   Translate_CSG, Rotate_CSG,
  92.   Scale_CSG, Transform_CSG, Invert_CSG_Intersection, Destroy_CSG
  93. };
  94.  
  95.  
  96.  
  97. /*****************************************************************************
  98. *
  99. * FUNCTION
  100. *
  101. *   All_CSG_Union_Intersections
  102. *
  103. * INPUT
  104. *   
  105. * OUTPUT
  106. *   
  107. * RETURNS
  108. *   
  109. * AUTHOR
  110. *
  111. *   POV-Ray Team
  112. *   
  113. * DESCRIPTION
  114. *
  115. *   -
  116. *
  117. * CHANGES
  118. *
  119. *   Sep 1994 : Added code to count intersection tests. [DB]
  120. *
  121. ******************************************************************************/
  122.  
  123. static int All_CSG_Union_Intersections (Object, Ray, Depth_Stack)
  124. OBJECT *Object;
  125. RAY *Ray;
  126. ISTACK *Depth_Stack;
  127. {
  128.   int Found;
  129.   OBJECT *Current_Sib, *Clip;
  130.   ISTACK *Local_Stack;
  131.   INTERSECTION *Sibling_Intersection;
  132.  
  133.   Increase_Counter(stats[Ray_CSG_Union_Tests]);
  134.  
  135.   Found = FALSE;
  136.  
  137.   /* Use shortcut if no clip. */
  138.  
  139.   if ((Clip = Object->Clip) == NULL)
  140.   {
  141.     for (Current_Sib = ((CSG *)Object)->Children; Current_Sib != NULL; Current_Sib = Current_Sib->Sibling)
  142.     {
  143.       if (Ray_In_Bound (Ray, Current_Sib->Bound))
  144.       {
  145.         if (All_Intersections (Current_Sib, Ray, Depth_Stack))
  146.         {
  147.           Found = TRUE;
  148.         }
  149.       }
  150.     }
  151.   }
  152.   else
  153.   {
  154.     Local_Stack = open_istack();
  155.  
  156.     for (Current_Sib = ((CSG *)Object)->Children; Current_Sib != NULL; Current_Sib = Current_Sib->Sibling)
  157.     {
  158.       if (Ray_In_Bound (Ray, Current_Sib->Bound))
  159.       {
  160.         if (All_Intersections (Current_Sib, Ray, Local_Stack))
  161.         {
  162.           while ((Sibling_Intersection = pop_entry(Local_Stack)) != NULL)
  163.           {
  164.             if (Point_In_Clip (Sibling_Intersection->IPoint, Clip))
  165.             {
  166.               push_copy (Depth_Stack, Sibling_Intersection);
  167.  
  168.               Found = TRUE;
  169.             }
  170.           }
  171.         }
  172.       }
  173.     }
  174.  
  175.     close_istack (Local_Stack);
  176.   }
  177.  
  178.   if (Found)
  179.   {
  180.     Increase_Counter(stats[Ray_CSG_Union_Tests_Succeeded]);
  181.   }
  182.  
  183.   return (Found);
  184. }
  185.  
  186.  
  187.  
  188. /*****************************************************************************
  189. *
  190. * FUNCTION
  191. *
  192. *   All_CSG_Intersection_Intersections
  193. *
  194. * INPUT
  195. *
  196. * OUTPUT
  197. *
  198. * RETURNS
  199. *
  200. * AUTHOR
  201. *
  202. *   POV-Ray Team
  203. *
  204. * DESCRIPTION
  205. *
  206. *   -
  207. *
  208. * CHANGES
  209. *
  210. *   Sep 1994 : Added code to count intersection tests. [DB]
  211. *
  212. ******************************************************************************/
  213.  
  214. static int All_CSG_Intersect_Intersections (Object, Ray, Depth_Stack)
  215. OBJECT *Object;
  216. RAY *Ray;
  217. ISTACK *Depth_Stack;
  218. {
  219.   int Maybe_Found, Found;
  220.   OBJECT *Current_Sib, *Inside_Sib;
  221.   ISTACK *Local_Stack;
  222.   INTERSECTION *Sibling_Intersection;
  223.  
  224.   Increase_Counter(stats[Ray_CSG_Intersection_Tests]);
  225.  
  226.   Local_Stack = open_istack ();
  227.  
  228.   Found = FALSE;
  229.  
  230.   for (Current_Sib = ((CSG *)Object)->Children; Current_Sib != NULL; Current_Sib = Current_Sib->Sibling)
  231.   {
  232.     if (Ray_In_Bound (Ray, Current_Sib->Bound))
  233.     {
  234.       if (All_Intersections (Current_Sib, Ray, Local_Stack))
  235.       {
  236.         while ((Sibling_Intersection = pop_entry(Local_Stack)) != NULL)
  237.         {
  238.           Maybe_Found = TRUE;
  239.  
  240.           for (Inside_Sib = ((CSG *)Object)->Children; Inside_Sib != NULL; Inside_Sib = Inside_Sib->Sibling)
  241.           {
  242.             if (Inside_Sib != Current_Sib)
  243.             {
  244.               if (!Inside_Object (Sibling_Intersection->IPoint, Inside_Sib))
  245.               {
  246.                 Maybe_Found = FALSE;
  247.  
  248.                 break;
  249.               }
  250.             }
  251.           }
  252.  
  253.           if (Maybe_Found)
  254.           {
  255.             if (Point_In_Clip (Sibling_Intersection->IPoint, Object->Clip))
  256.             {
  257.               push_copy(Depth_Stack, Sibling_Intersection);
  258.  
  259.               Found = TRUE;
  260.             }
  261.           }
  262.         }
  263.       }
  264.     }
  265.   }
  266.  
  267.   close_istack (Local_Stack);
  268.  
  269.   if (Found)
  270.   {
  271.     Increase_Counter(stats[Ray_CSG_Intersection_Tests_Succeeded]);
  272.   }
  273.  
  274.   return (Found);
  275. }
  276.  
  277.  
  278.  
  279. /*****************************************************************************
  280. *
  281. * FUNCTION
  282. *
  283. *   All_CSG_Merge_Intersections
  284. *
  285. * INPUT
  286. *
  287. * OUTPUT
  288. *
  289. * RETURNS
  290. *
  291. * AUTHOR
  292. *
  293. *   POV-Ray Team
  294. *
  295. * DESCRIPTION
  296. *
  297. *   -
  298. *
  299. * CHANGES
  300. *
  301. *   Sep 1994 : Added code to count intersection tests. [DB]
  302. *
  303. ******************************************************************************/
  304.  
  305. static int All_CSG_Merge_Intersections (Object, Ray, Depth_Stack)
  306. OBJECT *Object;
  307. RAY *Ray;
  308. ISTACK *Depth_Stack;
  309. {
  310.   int Found, inside_flag;
  311.   OBJECT *Sib1, *Sib2;
  312.   ISTACK *Local_Stack;
  313.   INTERSECTION *Sibling_Intersection;
  314.  
  315.   Increase_Counter(stats[Ray_CSG_Merge_Tests]);
  316.  
  317.   Found = FALSE;
  318.  
  319.   Local_Stack = open_istack ();
  320.  
  321.   for (Sib1 = ((CSG *)Object)->Children; Sib1 != NULL; Sib1 = Sib1->Sibling)
  322.   {
  323.     if (Ray_In_Bound (Ray, Sib1->Bound))
  324.     {
  325.       if (All_Intersections (Sib1, Ray, Local_Stack))
  326.       {
  327.         while ((Sibling_Intersection = pop_entry (Local_Stack)) !=  NULL)
  328.         {
  329.           if (Point_In_Clip (Sibling_Intersection->IPoint, Object->Clip))
  330.           {
  331.             inside_flag = TRUE;
  332.  
  333.             for (Sib2 = ((CSG *)Object)->Children; Sib2 != NULL && inside_flag == TRUE; Sib2 = Sib2->Sibling)
  334.             {
  335.               if (Sib1 != Sib2)
  336.               {
  337.                 if (Inside_Object(Sibling_Intersection->IPoint, Sib2))
  338.                 {
  339.                   inside_flag = FALSE;
  340.                 }
  341.               }
  342.             }
  343.  
  344.             if (inside_flag == TRUE)
  345.             {
  346.               Found = TRUE;
  347.  
  348.               push_copy (Depth_Stack, Sibling_Intersection);
  349.             }
  350.           }
  351.         }
  352.       }
  353.     }
  354.   }
  355.  
  356.   close_istack (Local_Stack);
  357.  
  358.   if (Found)
  359.   {
  360.     Increase_Counter(stats[Ray_CSG_Merge_Tests_Succeeded]);
  361.   }
  362.  
  363.   return (Found);
  364. }
  365.  
  366.  
  367.  
  368. /*****************************************************************************
  369. *
  370. * FUNCTION
  371. *
  372. *   Inside_CSG_Union
  373. *
  374. * INPUT
  375. *
  376. * OUTPUT
  377. *
  378. * RETURNS
  379. *
  380. * AUTHOR
  381. *
  382. *   POV-Ray Team
  383. *
  384. * DESCRIPTION
  385. *
  386. *   -
  387. *
  388. * CHANGES
  389. *
  390. *   -
  391. *
  392. ******************************************************************************/
  393.  
  394. static int Inside_CSG_Union (IPoint, Object)
  395. VECTOR IPoint;
  396. OBJECT *Object;
  397. {
  398.   OBJECT *Current_Sib;
  399.  
  400.   for (Current_Sib = ((CSG *)Object)->Children; Current_Sib != NULL; Current_Sib = Current_Sib->Sibling)
  401.   {
  402.     if (Inside_Object (IPoint, Current_Sib))
  403.     {
  404.       return (TRUE);
  405.     }
  406.   }
  407.  
  408.   return (FALSE);
  409. }
  410.  
  411.  
  412.  
  413. /*****************************************************************************
  414. *
  415. * FUNCTION
  416. *
  417. *   Inside_CSG_Intersection
  418. *
  419. * INPUT
  420. *
  421. * OUTPUT
  422. *
  423. * RETURNS
  424. *
  425. * AUTHOR
  426. *
  427. *   POV-Ray Team
  428. *
  429. * DESCRIPTION
  430. *
  431. *   -
  432. *
  433. * CHANGES
  434. *
  435. *   -
  436. *
  437. ******************************************************************************/
  438.  
  439. static int Inside_CSG_Intersection (IPoint, Object)
  440. OBJECT *Object;
  441. VECTOR IPoint;
  442. {
  443.   OBJECT *Current_Sib;
  444.  
  445.   for (Current_Sib = ((CSG *)Object)->Children; Current_Sib != NULL; Current_Sib = Current_Sib->Sibling)
  446.   {
  447.     if (!Inside_Object (IPoint, Current_Sib))
  448.     {
  449.       return (FALSE);
  450.     }
  451.   }
  452.  
  453.   return (TRUE);
  454. }
  455.  
  456.  
  457.  
  458. /*****************************************************************************
  459. *
  460. * FUNCTION
  461. *
  462. *   Translate_CSG
  463. *
  464. * INPUT
  465. *
  466. * OUTPUT
  467. *
  468. * RETURNS
  469. *
  470. * AUTHOR
  471. *
  472. *   POV-Ray Team
  473. *
  474. * DESCRIPTION
  475. *
  476. *   -
  477. *
  478. * CHANGES
  479. *
  480. *   -
  481. *
  482. ******************************************************************************/
  483.  
  484. static void Translate_CSG (Object, Vector, Trans)
  485. OBJECT *Object;
  486. VECTOR Vector;
  487. TRANSFORM *Trans;
  488. {
  489.   OBJECT *Sib;
  490.  
  491.   for (Sib = ((CSG *) Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  492.   {
  493.     Translate_Object(Sib, Vector, Trans);
  494.   }
  495.  
  496.   Recompute_BBox(&Object->BBox, Trans);
  497. }
  498.  
  499.  
  500.  
  501. /*****************************************************************************
  502. *
  503. * FUNCTION
  504. *
  505. *   Rotate_CSG
  506. *
  507. * INPUT
  508. *
  509. * OUTPUT
  510. *
  511. * RETURNS
  512. *
  513. * AUTHOR
  514. *
  515. *   POV-Ray Team
  516. *
  517. * DESCRIPTION
  518. *
  519. *   -
  520. *
  521. * CHANGES
  522. *
  523. *   -
  524. *
  525. ******************************************************************************/
  526.  
  527. static void Rotate_CSG (Object, Vector, Trans)
  528. OBJECT *Object;
  529. VECTOR Vector;
  530. TRANSFORM *Trans;
  531. {
  532.   OBJECT *Sib;
  533.  
  534.   for (Sib = ((CSG *) Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  535.   {
  536.     Rotate_Object(Sib, Vector, Trans);
  537.   }
  538.  
  539.   Recompute_BBox(&Object->BBox, Trans);
  540. }
  541.  
  542.  
  543.  
  544. /*****************************************************************************
  545. *
  546. * FUNCTION
  547. *
  548. *   Scale_CSG
  549. *
  550. * INPUT
  551. *
  552. * OUTPUT
  553. *
  554. * RETURNS
  555. *
  556. * AUTHOR
  557. *
  558. *   POV-Ray Team
  559. *
  560. * DESCRIPTION
  561. *
  562. *   -
  563. *
  564. * CHANGES
  565. *
  566. *   -
  567. *
  568. ******************************************************************************/
  569.  
  570. static void Scale_CSG (Object, Vector, Trans)
  571. OBJECT *Object;
  572. VECTOR Vector;
  573. TRANSFORM *Trans;
  574. {
  575.   OBJECT *Sib;
  576.  
  577.   for (Sib = ((CSG *) Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  578.   {
  579.     Scale_Object(Sib, Vector, Trans);
  580.   }
  581.  
  582.   Recompute_BBox(&Object->BBox, Trans);
  583. }
  584.  
  585.  
  586.  
  587. /*****************************************************************************
  588. *
  589. * FUNCTION
  590. *
  591. *   Transform_CSG
  592. *
  593. * INPUT
  594. *
  595. * OUTPUT
  596. *
  597. * RETURNS
  598. *
  599. * AUTHOR
  600. *
  601. *   POV-Ray Team
  602. *
  603. * DESCRIPTION
  604. *
  605. *   -
  606. *
  607. * CHANGES
  608. *
  609. *   -
  610. *
  611. ******************************************************************************/
  612.  
  613. static void Transform_CSG (Object, Trans)
  614. OBJECT *Object;
  615. TRANSFORM *Trans;
  616. {
  617.   OBJECT *Sib;
  618.  
  619.   for (Sib = ((CSG *) Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  620.   {
  621.     Transform_Object (Sib, Trans);
  622.   }
  623.  
  624.   Recompute_BBox(&Object->BBox, Trans);
  625. }
  626.  
  627.  
  628.  
  629. /*****************************************************************************
  630. *
  631. * FUNCTION
  632. *
  633. *   Invert_CSG_Union
  634. *
  635. * INPUT
  636. *
  637. * OUTPUT
  638. *
  639. * RETURNS
  640. *
  641. * AUTHOR
  642. *
  643. *   POV-Ray Team
  644. *
  645. * DESCRIPTION
  646. *
  647. *   -
  648. *
  649. * CHANGES
  650. *
  651. *   -
  652. *
  653. ******************************************************************************/
  654.  
  655. static void Invert_CSG_Union (Object)
  656. OBJECT *Object;
  657. {
  658.   OBJECT *Sib;
  659.  
  660.   Object->Methods = &CSG_Intersection_Methods;
  661.  
  662.   for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  663.   {
  664.     Invert_Object (Sib);
  665.   }
  666.  
  667.   Invert_Flag(Object, INVERTED_FLAG);
  668. }
  669.  
  670.  
  671.  
  672. /*****************************************************************************
  673. *
  674. * FUNCTION
  675. *
  676. *   Invert_CSG_Intersection
  677. *
  678. * INPUT
  679. *
  680. * OUTPUT
  681. *
  682. * RETURNS
  683. *
  684. * AUTHOR
  685. *
  686. *   POV-Ray Team
  687. *
  688. * DESCRIPTION
  689. *
  690. *   -
  691. *
  692. * CHANGES
  693. *
  694. *   -
  695. *
  696. ******************************************************************************/
  697.  
  698. static void Invert_CSG_Intersection (Object)
  699. OBJECT *Object;
  700. {
  701.   OBJECT *Sib;
  702.  
  703.   Object->Methods = &CSG_Union_Methods;
  704.  
  705.   for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  706.   {
  707.     Invert_Object (Sib);
  708.   }
  709.  
  710.   Invert_Flag(Object, INVERTED_FLAG);
  711. }
  712.  
  713.  
  714.  
  715. /*****************************************************************************
  716. *
  717. * FUNCTION
  718. *
  719. *   Create_CSG_Union
  720. *
  721. * INPUT
  722. *
  723. * OUTPUT
  724. *
  725. * RETURNS
  726. *
  727. * AUTHOR
  728. *
  729. *   POV-Ray Team
  730. *
  731. * DESCRIPTION
  732. *
  733. *   -
  734. *
  735. * CHANGES
  736. *
  737. *   -
  738. *
  739. ******************************************************************************/
  740.  
  741. CSG *Create_CSG_Union ()
  742. {
  743.   CSG *New;
  744.  
  745.   New = (CSG *)POV_MALLOC(sizeof (CSG), "union");
  746.  
  747.   INIT_OBJECT_FIELDS(New, UNION_OBJECT, &CSG_Union_Methods)
  748.  
  749.   New->Children = NULL;
  750.  
  751.   return (New);
  752. }
  753.  
  754.  
  755.  
  756. /*****************************************************************************
  757. *
  758. * FUNCTION
  759. *
  760. *   Create_CSG_Merge
  761. *
  762. * INPUT
  763. *
  764. * OUTPUT
  765. *
  766. * RETURNS
  767. *
  768. * AUTHOR
  769. *
  770. *   POV-Ray Team
  771. *
  772. * DESCRIPTION
  773. *
  774. *   -
  775. *
  776. * CHANGES
  777. *
  778. *   -
  779. *
  780. ******************************************************************************/
  781.  
  782. CSG *Create_CSG_Merge ()
  783. {
  784.   CSG *New;
  785.  
  786.   New = (CSG *)POV_MALLOC(sizeof (CSG), "merge");
  787.  
  788.   INIT_OBJECT_FIELDS(New, MERGE_OBJECT, &CSG_Merge_Methods)
  789.  
  790.   New->Children = NULL;
  791.  
  792.   return (New);
  793. }
  794.  
  795.  
  796.  
  797. /*****************************************************************************
  798. *
  799. * FUNCTION
  800. *
  801. *   Create_CSG_Intersection
  802. *
  803. * INPUT
  804. *
  805. * OUTPUT
  806. *
  807. * RETURNS
  808. *
  809. * AUTHOR
  810. *
  811. *   POV-Ray Team
  812. *
  813. * DESCRIPTION
  814. *
  815. *   -
  816. *
  817. * CHANGES
  818. *
  819. *   -
  820. *
  821. ******************************************************************************/
  822.  
  823. CSG *Create_CSG_Intersection ()
  824. {
  825.   CSG *New;
  826.  
  827.   New = (CSG *)POV_MALLOC(sizeof (CSG), "intersection");
  828.  
  829.   INIT_OBJECT_FIELDS(New, INTERSECTION_OBJECT, &CSG_Intersection_Methods)
  830.  
  831.   New->Children = NULL;
  832.  
  833.   return (New);
  834. }
  835.  
  836.  
  837.  
  838. /*****************************************************************************
  839. *
  840. * FUNCTION
  841. *
  842. *   Copy_CSG
  843. *
  844. * INPUT
  845. *
  846. * OUTPUT
  847. *
  848. * RETURNS
  849. *
  850. * AUTHOR
  851. *
  852. *   POV-Ray Team
  853. *
  854. * DESCRIPTION
  855. *
  856. *   -
  857. *
  858. * CHANGES
  859. *
  860. *   -
  861. *
  862. ******************************************************************************/
  863.  
  864. static void *Copy_CSG (Object)
  865. OBJECT *Object;
  866. {
  867.   CSG *New;
  868.   OBJECT *Old_Sib, *New_Sib, *Prev_Sib;
  869.  
  870.   New = (CSG *)POV_MALLOC(sizeof (CSG), "csg");
  871.  
  872.   *New = *(CSG *)Object;
  873.  
  874.   New->Children = Prev_Sib = NULL;
  875.  
  876.   for (Old_Sib = ((CSG *)Object)->Children; Old_Sib != NULL; Old_Sib = Old_Sib->Sibling)
  877.   {
  878.     New_Sib = Copy_Object (Old_Sib);
  879.  
  880.     if (New->Children == NULL)
  881.     {
  882.       New->Children = New_Sib;
  883.     }
  884.  
  885.     if (Prev_Sib != NULL)
  886.     {
  887.       Prev_Sib->Sibling = New_Sib;
  888.     }
  889.  
  890.     Prev_Sib = New_Sib;
  891.   }
  892.  
  893.   return (New);
  894. }
  895.  
  896.  
  897.  
  898. /*****************************************************************************
  899. *
  900. * FUNCTION
  901. *
  902. *   Destroy_CSG
  903. *
  904. * INPUT
  905. *
  906. * OUTPUT
  907. *
  908. * RETURNS
  909. *
  910. * AUTHOR
  911. *
  912. *   POV-Ray Team
  913. *
  914. * DESCRIPTION
  915. *
  916. *   -
  917. *
  918. * CHANGES
  919. *
  920. *   -
  921. *
  922. ******************************************************************************/
  923.  
  924. static void Destroy_CSG (Object)
  925. OBJECT *Object;
  926. {
  927.   Destroy_Object (((CSG *) Object)->Children);
  928.  
  929.   POV_FREE (Object);
  930. }
  931.  
  932.  
  933.  
  934. /*****************************************************************************
  935. *
  936. * FUNCTION
  937. *
  938. *   Compute_CSG_BBox
  939. *
  940. * INPUT
  941. *
  942. * OUTPUT
  943. *
  944. * RETURNS
  945. *
  946. * AUTHOR
  947. *
  948. *   POV-Ray Team
  949. *
  950. * DESCRIPTION
  951. *
  952. *   -
  953. *
  954. * CHANGES
  955. *
  956. *   Sep 1994 : Improved bounding of quadrics used in CSG intersections. [DB]
  957. *
  958. ******************************************************************************/
  959.  
  960. void Compute_CSG_BBox (Object)
  961. OBJECT *Object;
  962. {
  963.   int i, count;
  964.   DBL Old_Volume, New_Volume;
  965.   VECTOR NewMin, NewMax, TmpMin, TmpMax, Min, Max;
  966.   OBJECT *Sib;
  967.   QUADRIC **Quadrics;
  968.  
  969.   if (Object->Methods == &CSG_Intersection_Methods)
  970.   {
  971.     /*
  972.      * Calculate the bounding box of a CSG intersection
  973.      * by intersecting the bounding boxes of all children.
  974.      */
  975.  
  976.     Make_Vector(NewMin, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  977.     Make_Vector(NewMax,  BOUND_HUGE,  BOUND_HUGE,  BOUND_HUGE);
  978.  
  979.     count = 0;
  980.  
  981.     Quadrics = NULL;
  982.  
  983.     /* Process all children. */
  984.  
  985.     for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  986.     {
  987.       /* Inverted objects and height fields mustn't be considered */
  988.  
  989.       if (!Test_Flag(Sib, INVERTED_FLAG) && (Sib->Methods != &HField_Methods))
  990.       {
  991.         /* Store quadrics since they'll be processed last. */
  992.  
  993.         if (Sib->Methods == &Quadric_Methods)
  994.         {
  995.           Quadrics = (QUADRIC **)POV_REALLOC(Quadrics, (count+1)*sizeof(QUADRIC *), "temporary quadric list");
  996.  
  997.           Quadrics[count++] = (QUADRIC *)Sib;
  998.         }
  999.         else
  1000.         {
  1001.           if (Sib->Methods == &Plane_Methods)
  1002.           {
  1003.             Compute_Plane_Min_Max((PLANE *)Sib, TmpMin, TmpMax);
  1004.           }
  1005.           else
  1006.           {
  1007.             Make_min_max_from_BBox(TmpMin, TmpMax, Sib->BBox);
  1008.           }
  1009.  
  1010.           NewMin[X] = max(NewMin[X], TmpMin[X]);
  1011.           NewMin[Y] = max(NewMin[Y], TmpMin[Y]);
  1012.           NewMin[Z] = max(NewMin[Z], TmpMin[Z]);
  1013.           NewMax[X] = min(NewMax[X], TmpMax[X]);
  1014.           NewMax[Y] = min(NewMax[Y], TmpMax[Y]);
  1015.           NewMax[Z] = min(NewMax[Z], TmpMax[Z]);
  1016.         }
  1017.       }
  1018.     }
  1019.  
  1020.     /* Process any quadrics. */
  1021.  
  1022.     for (i = 0; i < count; i++)
  1023.     {
  1024.       Assign_Vector(Min, NewMin);
  1025.       Assign_Vector(Max, NewMax);
  1026.  
  1027.       Compute_Quadric_BBox(Quadrics[i], Min, Max);
  1028.  
  1029.       Make_min_max_from_BBox(TmpMin, TmpMax, Quadrics[i]->BBox);
  1030.  
  1031.       NewMin[X] = max(NewMin[X], TmpMin[X]);
  1032.       NewMin[Y] = max(NewMin[Y], TmpMin[Y]);
  1033.       NewMin[Z] = max(NewMin[Z], TmpMin[Z]);
  1034.       NewMax[X] = min(NewMax[X], TmpMax[X]);
  1035.       NewMax[Y] = min(NewMax[Y], TmpMax[Y]);
  1036.       NewMax[Z] = min(NewMax[Z], TmpMax[Z]);
  1037.     }
  1038.  
  1039.     if (Quadrics != NULL)
  1040.     {
  1041.       POV_FREE(Quadrics);
  1042.     }
  1043.   }
  1044.   else
  1045.   {
  1046.     /* Calculate the bounding box of a CSG merge/union object. */
  1047.  
  1048.     Make_Vector(NewMin,  BOUND_HUGE,  BOUND_HUGE,  BOUND_HUGE);
  1049.     Make_Vector(NewMax, -BOUND_HUGE, -BOUND_HUGE, -BOUND_HUGE);
  1050.  
  1051.     for (Sib = ((CSG *)Object)->Children; Sib != NULL; Sib = Sib->Sibling)
  1052.     {
  1053.       Make_min_max_from_BBox(TmpMin, TmpMax, Sib->BBox);
  1054.  
  1055.       NewMin[X] = min(NewMin[X], TmpMin[X]);
  1056.       NewMin[Y] = min(NewMin[Y], TmpMin[Y]);
  1057.       NewMin[Z] = min(NewMin[Z], TmpMin[Z]);
  1058.       NewMax[X] = max(NewMax[X], TmpMax[X]);
  1059.       NewMax[Y] = max(NewMax[Y], TmpMax[Y]);
  1060.       NewMax[Z] = max(NewMax[Z], TmpMax[Z]);
  1061.     }
  1062.   }
  1063.  
  1064.   if ((NewMin[X] > NewMax[X]) || (NewMin[Y] > NewMax[Y]) || (NewMin[Z] > NewMax[Z]))
  1065.   {
  1066.     Warning(0.0, "Degenerate CSG bounding box (not used!).\n");
  1067.   }
  1068.   else
  1069.   {
  1070.     New_Volume = (NewMax[X] - NewMin[X]) * (NewMax[Y] - NewMin[Y]) * (NewMax[Z] - NewMin[Z]);
  1071.  
  1072.     BOUNDS_VOLUME(Old_Volume, Object->BBox);
  1073.  
  1074.     if (New_Volume < Old_Volume)
  1075.     {
  1076.       Make_BBox_from_min_max(Object->BBox, NewMin, NewMax);
  1077.  
  1078.       /* Beware of bounding boxes to large. */
  1079.  
  1080.       if ((Object->BBox.Lengths[X] > CRITICAL_LENGTH) ||
  1081.           (Object->BBox.Lengths[Y] > CRITICAL_LENGTH) ||
  1082.           (Object->BBox.Lengths[Z] > CRITICAL_LENGTH))
  1083.       {
  1084.         Make_BBox(Object->BBox, -BOUND_HUGE/2, -BOUND_HUGE/2, -BOUND_HUGE/2,
  1085.           BOUND_HUGE, BOUND_HUGE, BOUND_HUGE);
  1086.       }
  1087.     }
  1088.   }
  1089. }
  1090.